import { Container } from "../Container";
import { BaseGui } from "../Services/BaseGui";
import { DataService } from "../Services/DataService";
import { ModelManService } from "../Services/ModelManService";
import { ViewerService } from "../Services/ViewerService";

export class TileMapGui extends BaseGui {
    title: string = `GIS地图[${TileMapGui.name}]`;
    private dataService = Container.defineProperty(DataService);
    private viewerService = Container.defineProperty(ViewerService);
    private modelManService = Container.defineProperty(ModelManService);
    protected UpdateGui(): void {
        let fun = {
            visible: false,
            position: "",
            rotation: "",
            scale: "",
            tile: "",
            tileGet:"",
            _Changed: async () => {
                let data = this.getData();
                data.visible = fun.visible;
                data.tileGet = fun.tileGet;
                data.tile = JSON.parse(fun.tile);
                data.position = JSON.parse(fun.position);
                data.rotation = JSON.parse(fun.rotation);
                data.scale = JSON.parse(fun.scale);
                this.updateViewer();
            },
            _Refresh: () => {
                let data = Object.assign(this.defaultMapData, this.getData());
                fun.visible = data.visible;
                fun.tileGet = data.tileGet;
                fun.tile = JSON.stringify(data.tile);
                fun.position = JSON.stringify(data.position);
                fun.rotation = JSON.stringify(data.rotation);
                fun.scale = JSON.stringify(data.scale);
            }
        }
        fun._Refresh();


        let gui = this.gui;
        let updateGUI = () => {
            Array.from(gui.__controllers).forEach(_ => {
                gui.remove(_);
            });
            this.guiService.buildGUIByObject(this.gui, fun);
        }
        updateGUI();
    }
    defaultMapData: MapData = {
        visible: false,
        tile: {
            lon: 113.482004,
            lat: 34.806612,
            zoom: 15,
            size: 4,
        },
        tileGet: "(x, y, z, s) => `http://webst0${s}.is.autonavi.com/appmaptile?x=${x}&y=${y}&z=${z}&lang=zh_cn&size=1&scale=1&style=6`",
        position: [0, 0, 0],
        rotation: [0, 0, 0],
        scale: [13.5, 13.5, 1]
    }
    Init(): void {
        this.dataService.OnDataChanged.addEventListener(() => {
            this.Refresh();
        });
        this.modelManService.UpdateChanged.addEventListener(() => {
            this.updateViewer();
        })
    }
    private getData(): MapData {
        if (!this.dataService.Data.tileMap) {
            this.dataService.Data.tileMap = {};
        }
        return this.dataService.Data.tileMap;
    }
    private async updateViewer() {
        let map = await this.viewerService.getTileMap();
        let data = this.getData();
        if (data.visible) {
            let config = map.Config || {};
            let tileGet = eval(data.tileGet);
            config.tileGet = (x, y) => {
                x += this.lon2tile(data.tile.lon, data.tile.zoom);
                y += this.lat2tile(data.tile.lat, data.tile.zoom);
                let z = data.tile.zoom;
                let s = Math.floor(Math.random() * 3 + 1);
                return tileGet(x, y, z, s);
                //return `http://webst0${s}.is.autonavi.com/appmaptile?x=${x}&y=${y}&z=${z}&lang=zh_cn&size=1&scale=1&style=6`;
            }
            //@ts-ignore
            config.tileSize = data.tile.size;
            //@ts-ignore
            config.position = data.position;
            //@ts-ignore
            config.rotation = data.rotation;
            //@ts-ignore
            config.scale = data.scale;
            map.Config = config;
            map.Show();
        }
        else
            map.Hide();
    }

    // 经纬度转瓦片编号
    lon2tile(lon: number, zoom: number) {
        return Math.floor((lon + 180) / 360 * Math.pow(2, zoom));
    }
    lat2tile(lat: number, zoom: number) {
        return Math.floor((1 - Math.log(Math.tan(lat * Math.PI / 180) + 1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, zoom));
    }

    // 瓦片编号转经纬度
    tile2long(x: number, z: number) {
        return (x / Math.pow(2, z) * 360 - 180);
    }
    tile2lat(y: number, z: number) {
        var n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);
        return (180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))));
    }
}
type MapData = {
    visible: boolean,
    tile: {
        lon: number,
        lat: number,
        zoom: number,
        size: number,
    }
    tileGet: string,
    position: number[],
    rotation: number[],
    scale: number[]
}